﻿using Basic.WxApiRemoteModel;
using Basic.WxCollect;
using Basic.WxModel.WxMsgFilter;
using Basic.WxRemoteModel.WxMsg.Model;
using Basic.WxService.Interface;
using WeDonekRpc.Client;
using WeDonekRpc.Client.Attr;
using WeDonekRpc.Client.Interface;
using WeDonekRpc.Client.Ioc;
using WeDonekRpc.Helper;

namespace Basic.WxService.WxMsg
{
    [ClassLifetimeAttr(ClassLifetimeType.SingleInstance)]
    internal class WxEventMsgFilterService : IWxEventMsgFilterService
    {
        private static IIocService _Ioc;

        private static WxMsgFilterDto[] _Filters = Array.Empty<WxMsgFilterDto>();

        private static Timer _SyncFilter;

        private readonly IRemoteSendService _SendService;
        private readonly IWxMsgEventLogCollect _MsgLog;
        private readonly IWxForwardLogCollect _ForwardLog;
        public WxEventMsgFilterService (IRemoteSendService sendService, IWxMsgEventLogCollect msgLog, IWxForwardLogCollect forwardLog)
        {
            this._SendService = sendService;
            this._MsgLog = msgLog;
            this._ForwardLog = forwardLog;
        }

        public static void Init ()
        {
            _Ioc = RpcClient.Ioc;
            _SyncFilter = new Timer(_Load, null, 1000, 60000);
        }
        private static void _Load (object state)
        {
            using (IocScope scope = _Ioc.CreateScore())
            {
                IWxMsgFilterCollect service = scope.Resolve<IWxMsgFilterCollect>();
                WxMsgFilterBase[] msgs = service.Gets(WxMsgFilterType.Event);
                if (msgs.Length == 0 && _Filters.Length == 0)
                {
                    return;
                }
                _Sync(msgs, service);
            }
        }
        private static void _Sync (WxMsgFilterBase[] msgs, IWxMsgFilterCollect service)
        {
            if (msgs.Length == 0)
            {
                _Filters = Array.Empty<WxMsgFilterDto>();
            }
            else if (_Filters.IsNull())
            {
                _Filters = service.GetFullFilter(msgs.ConvertAll(a => a.Id));
            }
            else
            {
                WxMsgFilterDto[] filters = _Filters.FindAll(c => msgs.IsExists(a => a.Id == c.Id && a.LastUpdateTime == c.LastUpdateTime));
                if (filters.Length == _Filters.Length)
                {
                    return;
                }
                long[] ids = msgs.Convert(a => !filters.IsExists(c => c.Id == a.Id), c => c.Id);
                WxMsgFilterDto[] dtos = service.GetFullFilter(ids);
                _Filters = dtos.Add(filters);
            }
        }
        public void SendMsg (WxMsgEventBody msg)
        {
            this._MsgLog.Add(msg);
            if (_Filters.IsNull())
            {
                return;
            }
            WxMsgFilterDto[] filters = _Filters.FindAll(c => c.MsgType == msg.EventType && c.AppId == msg.PlatformAppId && ( c.WxAppId == msg.WxAppId || c.WxAppId == null ));
            if (!filters.IsNull())
            {
                filters.ForEach(c =>
                {
                    try
                    {
                        c.Send(this._SendService, msg);
                    }
                    catch (ErrorException e)
                    {
                        this._ForwardLog.Add(msg, c, e);
                        if (e.IsSystemError)
                        {
                            e.SaveLog("WxMsg");
                        }
                    }
                });
            }
        }
    }
}
